﻿using LibBinary.FileDeclaration;
using LibBinary.FileDeclaration.Binary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GSPatEditor.Serialization
{
    static class PatFileFormatProvider
    {
        public static readonly IFileDeclaration Format = CreatePatDeclaration();

        private static IFileDeclaration CreatePatDeclaration()
        {
            return new StructuredDeclaration(new IFileDeclaration[] {
                //file type (5)
                new ConstantDeclaration<byte>(5),

                //image list
                new StructuredDeclaration(new IFileDeclaration[] {
                    new PrimitiveDeclaration(PrimitiveType.Int16),
                    new ArrayDeclaration(new ReferenceLengthProvider(0), 
                        new StringDeclaration(new ConstLengthProvider(0x80), Encoding.ASCII)
                    ),
                }),

                //animation list
                new StructuredDeclaration(new IFileDeclaration[] {
                    new PrimitiveDeclaration(PrimitiveType.Int32),
                    new ArrayDeclaration(new ReferenceLengthProvider(0),
                        //a single animation
                        new StructuredDeclaration(new IFileDeclaration[] {
                            new FieldDeclaration("AnimationID", SimpleFieldArrangement.Instance,
                                new PrimitiveDeclaration(PrimitiveType.Int32)
                            ),
                            new RelativeReferenceDeclaration(0, 0),
                            #region CloneAnimation
                            new ConditionalDeclaration(new ReferenceIntConditionProvider(1, ConditionIntCompare.Equal, -1),
                                new StructuredDeclaration(new IFileDeclaration[] {
                                    new FieldDeclaration("CloneFrom", SimpleFieldArrangement.Instance,
                                        new PrimitiveDeclaration(PrimitiveType.Int16)
                                    ),
                                    new FieldDeclaration("CloneTo", SimpleFieldArrangement.Instance,
                                        new PrimitiveDeclaration(PrimitiveType.Int16)
                                    ),
                                })
                            ),
                            #endregion
                            #region NormalAnimation
                            new ConditionalDeclaration(new ReferenceIntConditionProvider(1, ConditionIntCompare.NotEqual, -1),
                                new StructuredDeclaration(new IFileDeclaration[] {
                                    new FieldDeclaration("AttackLevel", SimpleFieldArrangement.Instance,
                                        new PrimitiveDeclaration(PrimitiveType.Int16)
                                    ),
                                    new FieldDeclaration("CancelLevel", SimpleFieldArrangement.Instance,
                                        new PrimitiveDeclaration(PrimitiveType.Int16)
                                    ),
                                    new FieldDeclaration("Loop", SimpleFieldArrangement.Instance,
                                        new PrimitiveDeclaration(PrimitiveType.Boolean)
                                    ),
                                    //frame list
                                    new StructuredDeclaration(new IFileDeclaration[] {
                                        new PrimitiveDeclaration(PrimitiveType.Int32),
                                        new ArrayDeclaration(new ReferenceLengthProvider(0),
                                            //a single frame
                                            new StructuredDeclaration(new IFileDeclaration[] {
                                                new FieldDeclaration("SpriteID", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                ),
                                                new FieldDeclaration("ViewOffsetX", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("ViewOffsetY", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("ViewWidth", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("ViewHeight", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("OriginX", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("OriginY", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("DisplayTime", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("ImageManipulation", SimpleFieldArrangement.Instance,
                                                    new StructuredDeclaration(new IFileDeclaration[] {
                                                        new PrimitiveDeclaration(PrimitiveType.Byte), //TURE:2,FALSE:1
                                                        new ConditionalDeclaration(new ReferenceIntConditionProvider(0, ConditionIntCompare.Equal, 2),
                                                            new StructuredDeclaration(new IFileDeclaration[] {
                                                                new FieldDeclaration("AlphaBlend", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                                ),
                                                                new FieldDeclaration("Alpha", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Byte)
                                                                ),
                                                                new FieldDeclaration("Red", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Byte)
                                                                ),
                                                                new FieldDeclaration("Green", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Byte)
                                                                ),
                                                                new FieldDeclaration("Blue", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Byte)
                                                                ),
                                                                new FieldDeclaration("ScaleX", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                                ),
                                                                new FieldDeclaration("ScaleY", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                                ),
                                                                new FieldDeclaration("SkewX", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                                ),
                                                                new FieldDeclaration("SkewY", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                                ),
                                                                new FieldDeclaration("Rotation", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                                ),
                                                            })
                                                        )
                                                    })
                                                ),
                                                new FieldDeclaration("AttackRate", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("HitStopOther", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("HitStopSelf", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Bind", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero1", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero2", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero3", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero4", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero5", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero6", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero7", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero8", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero9", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero10", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero11", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero12", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero13", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("HitSoundEffect", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("AttackType", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero14", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("Zero15", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Byte)
                                                ),
                                                new FieldDeclaration("StateFlag", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                ),
                                                new FieldDeclaration("AttackFlag", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                ),
                                                new FieldDeclaration("Physics", SimpleFieldArrangement.Instance,
                                                    new StructuredDeclaration(new IFileDeclaration[] {
                                                        new PrimitiveDeclaration(PrimitiveType.Boolean),
                                                        new ConditionalDeclaration(new ReferenceBoolConditionProvider(0),
                                                            new StructuredDeclaration(new IFileDeclaration[] {
                                                                new FieldDeclaration("X1", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("Y1", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("X2", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("Y2", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                            })
                                                        )
                                                    })
                                                ),
                                                new FieldDeclaration("HitBoxes", SimpleFieldArrangement.Instance,
                                                    new StructuredDeclaration(new IFileDeclaration[] {
                                                        new PrimitiveDeclaration(PrimitiveType.Byte),
                                                        new ArrayDeclaration(new ReferenceLengthProvider(0),
                                                            new StructuredDeclaration(new IFileDeclaration[] {
                                                                new FieldDeclaration("X1", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("Y1", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("X2", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("Y2", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("Angle", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                                ),
                                                            })
                                                        )
                                                    })
                                                ),
                                                new FieldDeclaration("AttackBoxes", SimpleFieldArrangement.Instance,
                                                    new StructuredDeclaration(new IFileDeclaration[] {
                                                        new PrimitiveDeclaration(PrimitiveType.Byte),
                                                        new ArrayDeclaration(new ReferenceLengthProvider(0),
                                                            new StructuredDeclaration(new IFileDeclaration[] {
                                                                new FieldDeclaration("X1", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("Y1", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("X2", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("Y2", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int32)
                                                                ),
                                                                new FieldDeclaration("Angle", SimpleFieldArrangement.Instance,
                                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                                ),
                                                            })
                                                        )
                                                    })
                                                ),
                                                new FieldDeclaration("Points", SimpleFieldArrangement.Instance,
                                                    new ArrayDeclaration(new ConstLengthProvider(3),
                                                        new StructuredDeclaration(new IFileDeclaration[] {
                                                            new FieldDeclaration("X", SimpleFieldArrangement.Instance,
                                                                new PrimitiveDeclaration(PrimitiveType.Int16)
                                                            ),
                                                            new FieldDeclaration("XSign", SimpleFieldArrangement.Instance,
                                                                new PrimitiveDeclaration(PrimitiveType.Int16)
                                                            ),
                                                            new FieldDeclaration("Y", SimpleFieldArrangement.Instance,
                                                                new PrimitiveDeclaration(PrimitiveType.Int16)
                                                            ),
                                                            new FieldDeclaration("YSign", SimpleFieldArrangement.Instance,
                                                                new PrimitiveDeclaration(PrimitiveType.Int16)
                                                            ),
                                                        })
                                                    )
                                                ),
                                                new FieldDeclaration("HitVX", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("HitVY", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                                new FieldDeclaration("HitG", SimpleFieldArrangement.Instance,
                                                    new PrimitiveDeclaration(PrimitiveType.Int16)
                                                ),
                                            })
                                        ),
                                    }),
                                })
                            ),
                            #endregion
                        })
                    ),
                }),
            });
        }
    }
}
